package kth;

import robocode.HitByBulletEvent;
import robocode.Robot;
import robocode.HitRobotEvent;
import robocode.ScannedRobotEvent;
import robocode.Rules;
import java.awt.Color;

/**
 * Creates a robot that will move back and forth along one wall, firing at any enemy
 * robot scanned, and moving to the opposite wall if it hits another robot. The robot
 * fires with power proportional to the distance from the enemy (higher power for
 * closer enemies).
 * 
 * @author Kim
 * @version 1.1
 */
public class PacerEvader extends Robot {
  double fieldHeight; // The height of the field
  private double maxDist; // Maximum distance between robots
  private double minPower; // Minimum bullet power
  private double maxPower; // Maximum bullet power
  
  /**
   * Sets the robot's properties and defines its basic back and forth movement.
   */
  public void run() {
    // Set the colors for PacerEvader
    setBodyColor(Color.magenta);
    setGunColor(Color.white);
    setRadarColor(Color.pink);
    setBulletColor(Color.magenta);
    setScanColor(Color.magenta);
    
    // Get the values for all battle-related variables
    fieldHeight = getBattleFieldHeight();
    double fieldWidth = getBattleFieldWidth();
    maxDist = Math.sqrt(Math.pow(fieldHeight, 2) + Math.pow(fieldWidth,2)) - 2 * getWidth();
    minPower = Rules.MIN_BULLET_POWER;
    maxPower = Rules.MAX_BULLET_POWER;
    
    // Turn to the top of the screen and move to the upper wall, then orient so that
    // the robot will be able to move along the wall with its gun facing outward
    turnLeft(getHeading());
    ahead(fieldHeight - getY());
    turnRight(90);
    turnGunRight(90);
    
    // Keep moving back and forth along the wall, for the full length of the wall
    while (true) {
      ahead(fieldWidth);
      back(fieldWidth);
    }
  }
  
  /**
   * Fires at any scanned enemy robot. Uses power proportional to the enemy's distance
   * from PacerEvader.
   * 
   * @param e the robot that was scanned.
   */
  public void onScannedRobot(ScannedRobotEvent e) {
    // When an enemy robot is scanned, get its distance, then fire using power
    // proportional to that distance.
    fire(calculateFirePower(e.getDistance()));
  }
  
  /**
   * Moves PacerEvader to the opposite wall whenever it hits an enemy robot.
   * 
   * @param e the robot that was hit
   */
  public void onHitRobot(HitRobotEvent e) {
    // When a robot is hit, turn and move to the opposite wall, then orient PacerEvader
    // so that it is again facing left-to-right, with its gun pointing into the 
    // battle field.
    turnRight(90);
    ahead(fieldHeight);
    turnRight(90);
  }
  
  /**
   * Moves PacerEvader to the opposite wall whenever it is hit by a bullet from the
   * front or the back. This is to avoid continuous attacks from Walls-based robots.
   * 
   * @param e the bullet that hit PacerEvader.
   */
  public void onHitByBullet(HitByBulletEvent e) {
    final double bulletBearing = e.getBearing(); // The direction the bullet came from
    
    // If the bullet came from directly in front or in back, plus or minus 20 degrees 
    // of PacerEvader, move to the opposite wall.
    if (Math.abs(bulletBearing) > 160 || Math.abs(bulletBearing) < 20) {
      turnRight(90);
      ahead(fieldHeight);
      turnRight(90);
    }
  }
  
  /**
   * Calculates the power the robot should fire at, using power proportional to the distance
   * the enemy robot is from PacerEvader.
   * 
   * @param d the distance from the enemy robot
   * @return the power to use to fire
   */
  public double calculateFirePower(double d) {
    return minPower + (maxDist - d) / maxDist * (maxPower - minPower);
  }
}
